package ltd.trackan.graphvalidatecode.service.impl;

import ltd.trackan.common.model.entity.RestBean;
import ltd.trackan.commonredis.service.RedisService;
import ltd.trackan.graphvalidatecode.service.CaptchaService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

/**
 * @author wxa
 */
@Service
public class CaptchaServiceImpl implements CaptchaService {

    // 注入Redis服务
    @Resource
    private RedisService redisService;
    
    

    // 获取验证码图片
    @Override
    public void getCaptchaCodeImage(HttpServletResponse response) {
        try {
            // 调用输出验证码图片的方法
            outputCaptcha(response);
        } catch (IOException e) {
            // 抛出运行时异常
            throw new RuntimeException(e);
        }
    }

    // 获取验证码文本
    @Override
    public RestBean<String> getCaptchaCodeText() {
        // 生成随机字符串并转换为大写
        String randomString = getRandomString().toUpperCase();
        // 将验证码存入Redis，设置过期时间为3600秒
        redisService.hset("Captcha", randomString, randomString, 3600);
        // 返回成功结果，包含验证码文本
        return RestBean.success(randomString);
    }

    // 验证验证码
    @Override
    public RestBean<String> verification(String code) {
        // 将输入的验证码转换为大写
        code = code.toUpperCase();
        // 设置Redis中的键名
        String key = "Captcha";
        // 检查Redis中是否存在该验证码
        if (redisService.hget(key, code) == null) {
            // 验证码错误，返回失败结果
            return RestBean.failure("验证码错误");
        }
        // 验证码正确，从Redis中删除该验证码
        redisService.hdel(key, code);
        // 返回成功结果
        return RestBean.success();
    }

    // 定义验证码字符集
    private static final char[] CHARS = { '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
            'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };

    // 创建随机数生成器
    private static Random random = new Random();

    // 定义验证码长度
    private static final int CHARS_LENGTH = 4;

    // 定义干扰线数量
    private static final int RECT_NUMBER = 100;

    // 生成随机字符串
    private static String getRandomString() {
        // 创建StringBuilder对象
        StringBuilder builder = new StringBuilder();
        // 循环生成指定长度的随机字符
        for (int i = 0; i < CHARS_LENGTH; i++) {
            // 随机选择字符并添加到StringBuilder中
            builder.append(CHARS[random.nextInt(CHARS.length)]);
        }
        // 返回生成的随机字符串
        return builder.toString();
    }

    // 获取随机颜色
    private static Color getRandomColor() {
        // 返回随机颜色
        return new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255));
    }

    // 获取反色
    private static Color getReverseColor() {
        // 返回白色
        return new Color(255, 255, 255);
    }

    // 输出验证码图片
    public void outputCaptcha(HttpServletResponse response) throws IOException {
        // 设置响应头，防止缓存
        response.setDateHeader("Expires", 0);
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
        response.setHeader("Pragma", "no-cache");
        // 设置响应内容类型为JPEG图片
        response.setContentType("image/jpeg");

        // 生成随机字符串并转换为大写
        String randomString = getRandomString().toUpperCase();
        // 将验证码存入Redis，设置过期时间为3600秒
        redisService.hset("Captcha", randomString, randomString, 3600);
        // 定义图片宽度和高度
        int width = 100;
        int height = 35;
        // 获取随机颜色
        Color color = getRandomColor();
        // 获取反色
        Color reverse = getReverseColor();

        // 创建BufferedImage对象
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        // 获取Graphics2D对象
        Graphics2D g = bi.createGraphics();
        // 设置字体
        g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 16));
        // 设置背景颜色
        g.setColor(reverse);
        // 填充背景
        g.fillRect(0, 0, width, height);
        // 设置验证码颜色
        g.setColor(color);
        // 绘制验证码字符串
        g.drawString(randomString, 18, 20);
        // 绘制干扰线
        for (int i = 0, n = random.nextInt(RECT_NUMBER); i < n; i++) {
            g.drawRect(random.nextInt(width), random.nextInt(height), 1, 1);
        }

        // 获取响应输出流
        ServletOutputStream out = response.getOutputStream();
        // 将BufferedImage写入输出流
        ImageIO.write(bi, "png", out);
        // 刷新输出流
        out.flush();
    }
}